/**
 * 消息路由器
 * 处理不同类型的消息路由和分发
 */

const EventEmitter = require('events');
const Logger = require('../utils/logger');
const MessageValidator = require('../utils/validator');
const config = require('../utils/config');

class MessageRouter extends EventEmitter {
  constructor(connectionManager) {
    super();
    this.connectionManager = connectionManager;
    this.validator = new MessageValidator();
    this.logger = new Logger('MessageRouter');
    this.messageHistory = []; // 消息历史记录
    this.messageHandlers = new Map(); // 消息处理器映射
    
    this.setupMessageHandlers();
  }

  /**
   * 设置消息处理器
   */
  setupMessageHandlers() {
    this.messageHandlers.set('join', this.handleJoinMessage.bind(this));
    this.messageHandlers.set('leave', this.handleLeaveMessage.bind(this));
    this.messageHandlers.set('message', this.handleChatMessage.bind(this));
    this.messageHandlers.set('private', this.handlePrivateMessage.bind(this));
    this.messageHandlers.set('broadcast', this.handleBroadcastMessage.bind(this));
    this.messageHandlers.set('ping', this.handlePingMessage.bind(this));
    this.messageHandlers.set('status', this.handleStatusMessage.bind(this));
  }

  /**
   * 处理收到的消息
   */
  async handleMessage(clientId, rawMessage) {
    try {
      // 解析消息
      let message;
      try {
        message = JSON.parse(rawMessage);
      } catch (error) {
        this.sendError(clientId, 'INVALID_JSON', '消息格式错误');
        return;
      }

      // 验证消息格式
      const validation = this.validator.validateFormat(message);
      if (!validation.valid) {
        this.sendError(clientId, 'INVALID_FORMAT', validation.error);
        return;
      }

      // 检查速率限制
      const rateLimitCheck = this.validator.checkRateLimit(
        clientId, 
        this.connectionManager.getRateLimitMap()
      );
      if (!rateLimitCheck.allowed) {
        this.sendError(clientId, 'RATE_LIMIT', rateLimitCheck.error);
        return;
      }

      // 设置消息来源
      message.from = clientId;
      
      // 获取连接信息
      const connection = this.connectionManager.getConnection(clientId);
      if (!connection) {
        this.sendError(clientId, 'CONNECTION_NOT_FOUND', '连接不存在');
        return;
      }

      // 记录消息
      this.logger.debug(`收到消息`, {
        clientId,
        type: message.type,
        userId: connection.userId,
        nickname: connection.nickname
      });

      // 路由消息到对应处理器
      const handler = this.messageHandlers.get(message.type);
      if (handler) {
        await handler(clientId, message, connection);
      } else {
        this.sendError(clientId, 'UNKNOWN_MESSAGE_TYPE', `未知的消息类型: ${message.type}`);
      }

      // 发出消息事件
      this.emit('message:processed', {
        clientId,
        message,
        connection,
        timestamp: new Date()
      });

    } catch (error) {
      this.logger.error(`处理消息失败`, {
        clientId,
        error: error.message,
        stack: error.stack
      });
      this.sendError(clientId, 'INTERNAL_ERROR', '服务器内部错误');
    }
  }

  /**
   * 处理用户加入消息
   */
  async handleJoinMessage(clientId, message, connection) {
    const { userId, nickname } = message.content || {};
    
    if (!userId || !nickname) {
      this.sendError(clientId, 'MISSING_USER_INFO', '缺少用户ID或昵称');
      return;
    }

    // 验证昵称
    const nicknameValidation = this.validator.validateNickname(nickname);
    if (!nicknameValidation.valid) {
      this.sendError(clientId, 'INVALID_NICKNAME', nicknameValidation.error);
      return;
    }

    // 加入用户
    const joinResult = this.connectionManager.joinUser(clientId, userId, nickname);
    if (!joinResult.success) {
      this.sendError(clientId, 'JOIN_FAILED', joinResult.error);
      return;
    }

    // 发送成功响应
    const joinResponse = this.validator.createMessage('join', {
      success: true,
      userId,
      nickname,
      onlineUsers: this.connectionManager.getOnlineUsers(),
      messageHistory: this.getRecentMessageHistory()
    });
    
    this.connectionManager.sendToConnection(clientId, joinResponse);

    // 广播用户加入事件
    const joinNotification = this.validator.createMessage('broadcast', {
      type: 'user_joined',
      userId,
      nickname,
      timestamp: new Date().toISOString()
    }, 'system');

    this.connectionManager.broadcast(joinNotification, clientId);
    this.addToHistory(joinNotification);

    this.logger.info(`用户加入成功`, { clientId, userId, nickname });
  }

  /**
   * 处理用户离开消息
   */
  async handleLeaveMessage(clientId, message, connection) {
    if (!connection.userId) {
      this.sendError(clientId, 'NOT_JOINED', '用户未加入');
      return;
    }

    const { userId, nickname } = connection;
    
    // 处理用户离开
    const leaveResult = this.connectionManager.leaveUser(clientId);
    if (!leaveResult.success) {
      this.sendError(clientId, 'LEAVE_FAILED', leaveResult.error);
      return;
    }

    // 发送成功响应
    const leaveResponse = this.validator.createMessage('leave', {
      success: true
    });
    
    this.connectionManager.sendToConnection(clientId, leaveResponse);

    // 广播用户离开事件
    const leaveNotification = this.validator.createMessage('broadcast', {
      type: 'user_left',
      userId,
      nickname,
      timestamp: new Date().toISOString()
    }, 'system');

    this.connectionManager.broadcast(leaveNotification, clientId);
    this.addToHistory(leaveNotification);

    this.logger.info(`用户离开成功`, { clientId, userId, nickname });
  }

  /**
   * 处理聊天消息
   */
  async handleChatMessage(clientId, message, connection) {
    if (!connection.userId) {
      this.sendError(clientId, 'NOT_JOINED', '请先加入聊天室');
      return;
    }

    const { content } = message;
    if (!content || typeof content !== 'string') {
      this.sendError(clientId, 'INVALID_CONTENT', '消息内容无效');
      return;
    }

    // 创建聊天消息
    const chatMessage = this.validator.createMessage('message', content, connection.userId, null, {
      nickname: connection.nickname,
      timestamp: new Date().toISOString()
    });

    // 广播消息
    this.connectionManager.broadcast(chatMessage);
    this.addToHistory(chatMessage);

    this.logger.debug(`聊天消息已广播`, {
      clientId,
      userId: connection.userId,
      nickname: connection.nickname,
      contentLength: content.length
    });
  }

  /**
   * 处理私聊消息
   */
  async handlePrivateMessage(clientId, message, connection) {
    if (!connection.userId) {
      this.sendError(clientId, 'NOT_JOINED', '请先加入聊天室');
      return;
    }

    const { to, content } = message;
    if (!to || !content) {
      this.sendError(clientId, 'INVALID_PRIVATE_MESSAGE', '缺少接收者或消息内容');
      return;
    }

    // 检查目标用户是否在线
    const targetConnections = this.connectionManager.getConnectionsByUserId(to);
    if (targetConnections.length === 0) {
      this.sendError(clientId, 'USER_NOT_FOUND', '目标用户不在线');
      return;
    }

    // 创建私聊消息
    const privateMessage = this.validator.createMessage('private', content, connection.userId, to, {
      nickname: connection.nickname,
      timestamp: new Date().toISOString()
    });

    // 发送给目标用户
    const sentCount = this.connectionManager.sendToUser(to, privateMessage);
    
    // 发送确认给发送者
    const confirmMessage = this.validator.createMessage('private', {
      type: 'sent_confirmation',
      to,
      originalMessage: privateMessage,
      deliveredTo: sentCount
    });
    
    this.connectionManager.sendToConnection(clientId, confirmMessage);

    this.logger.debug(`私聊消息已发送`, {
      from: connection.userId,
      to,
      sentCount,
      contentLength: content.length
    });
  }

  /**
   * 处理广播消息
   */
  async handleBroadcastMessage(clientId, message, connection) {
    // 只有系统或管理员可以发送广播消息
    if (!this.isSystemOrAdmin(connection)) {
      this.sendError(clientId, 'PERMISSION_DENIED', '无权限发送广播消息');
      return;
    }

    const { content } = message;
    if (!content) {
      this.sendError(clientId, 'INVALID_CONTENT', '广播内容无效');
      return;
    }

    // 创建广播消息
    const broadcastMessage = this.validator.createMessage('broadcast', content, 'system', null, {
      timestamp: new Date().toISOString()
    });

    // 广播给所有用户
    this.connectionManager.broadcast(broadcastMessage);
    this.addToHistory(broadcastMessage);

    this.logger.info(`系统广播消息已发送`, {
      clientId,
      contentLength: JSON.stringify(content).length
    });
  }

  /**
   * 处理ping消息
   */
  async handlePingMessage(clientId, message, connection) {
    // 发送pong响应
    const pongMessage = this.validator.createMessage('pong', {
      timestamp: new Date().toISOString(),
      serverTime: Date.now()
    });
    
    this.connectionManager.sendToConnection(clientId, pongMessage);
    
    this.logger.debug(`Ping-Pong`, { clientId });
  }

  /**
   * 处理状态查询消息
   */
  async handleStatusMessage(clientId, message, connection) {
    const stats = this.connectionManager.getStats();
    const onlineUsers = this.connectionManager.getOnlineUsers();
    
    const statusMessage = this.validator.createMessage('status', {
      server: {
        uptime: process.uptime(),
        memory: process.memoryUsage(),
        timestamp: new Date().toISOString()
      },
      connections: stats,
      onlineUsers: onlineUsers,
      user: connection.userId ? {
        userId: connection.userId,
        nickname: connection.nickname,
        connectedAt: connection.connectedAt
      } : null
    });
    
    this.connectionManager.sendToConnection(clientId, statusMessage);
    
    this.logger.debug(`状态查询`, { clientId });
  }

  /**
   * 发送错误消息
   */
  sendError(clientId, code, message, details = null) {
    const errorMessage = this.validator.createMessage('error', {
      code,
      message,
      details,
      timestamp: new Date().toISOString()
    });
    
    this.connectionManager.sendToConnection(clientId, errorMessage);
    
    this.logger.warn(`发送错误消息`, { clientId, code, message });
  }

  /**
   * 添加消息到历史记录
   */
  addToHistory(message) {
    this.messageHistory.push({
      ...message,
      serverTimestamp: new Date().toISOString()
    });
    
    // 限制历史记录数量
    const historyLimit = config.get('message.historyLimit', 100);
    if (this.messageHistory.length > historyLimit) {
      this.messageHistory = this.messageHistory.slice(-historyLimit);
    }
  }

  /**
   * 获取最近的消息历史
   */
  getRecentMessageHistory(limit = 20) {
    return this.messageHistory.slice(-limit);
  }

  /**
   * 检查是否为系统或管理员
   */
  isSystemOrAdmin(connection) {
    // 简单的管理员检查逻辑
    // 在实际应用中，应该基于数据库或配置进行更复杂的权限验证
    const adminUserIds = ['admin', 'system'];
    return adminUserIds.includes(connection.userId);
  }

  /**
   * 获取消息统计
   */
  getMessageStats() {
    const now = Date.now();
    const oneHourAgo = now - 60 * 60 * 1000;
    
    const recentMessages = this.messageHistory.filter(msg => {
      const msgTime = new Date(msg.serverTimestamp).getTime();
      return msgTime > oneHourAgo;
    });
    
    const typeStats = {};
    recentMessages.forEach(msg => {
      typeStats[msg.type] = (typeStats[msg.type] || 0) + 1;
    });
    
    return {
      totalHistoryMessages: this.messageHistory.length,
      recentMessages: recentMessages.length,
      messageTypeStats: typeStats,
      averageMessagesPerHour: recentMessages.length
    };
  }

  /**
   * 清理消息历史
   */
  clearHistory() {
    const cleared = this.messageHistory.length;
    this.messageHistory = [];
    this.logger.info(`消息历史已清理`, { clearedMessages: cleared });
    return cleared;
  }
}

module.exports = MessageRouter;